home *** CD-ROM | disk | FTP | other *** search
- /*
- * Original Code:
- * Copyright (C) 1991, Commodore Business Machines, Inc.
- *
- * Assumes that copying code placed in chip ram is safe from being
- * overwritten. Also makes some assumptions about the ELF kernel,
- * including assuming that the loadable, merged text and data segment
- * is the first program segment (the first program header table entry)
- * for fully linked kernels.
- *
- * Uses bootmethod 3 (EXEC1):
- *
- * D0 = 3 // boot method 3
- * D1 = (struct bootinfo *) // pointer to boot information
- *
- * 91-12-10 mw Converted original boot2.c file into a standalone
- * program runnable from AmigaDOS.
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/nodes.h>
- #include <exec/libraries.h>
- #include <exec/io.h>
- #include <exec/execbase.h>
- #include <devices/trackdisk.h>
- #include <hardware/cia.h>
- #include <libraries/configregs.h>
- #include <libraries/configvars.h>
- #include <libraries/expansion.h>
- #include <libraries/expansionbase.h>
-
- #include <inline/exec.h>
-
- #define ABSEXECBASE ( (struct ExecBase **)4 )
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/elf.h>
- #include <stdio.h>
-
- extern int errno;
-
- /* I like even numbers ;-) */
- #define CHIP_BUF_SIZE 1024
-
- #define reloc(adr) (adr)
-
- #include "infoblock.h"
- #include "bootdata.h"
- #include "bootinfo.h" /* NAUTO, etc */
-
- #define min(a,b) ((a)<(b)?(a):(b))
-
- /*
- * Parameters to assembler "copyit" function.
- */
-
- struct copyinfo {
- unsigned char *ci_loadbuf;
- unsigned long ci_vaddr;
- unsigned long ci_size;
- unsigned long ci_entry;
- unsigned long ci_d0;
- unsigned long ci_d1;
- unsigned long ci_copyit[1]; /* Code gets copied here */
- };
-
-
- int
- main (int argc, char *argv[])
- {
- struct infoblock *infobuf; /* Buffer for kernel info block */
- unsigned long infobase; /* Offset of kernel info block */
- unsigned long filebase; /* Offset of kernel on boot dev */
- struct ExpansionBase *ExpansionBase;
- struct bootinfo *bi;
- struct BootData *bd;
- struct ConfigDev *cdp;
- struct ConfigDev *acp;
- struct MemHeader *mhp;
- struct MemHeader *mnp;
- unsigned long nbytes;
- unsigned long temp;
- struct copyinfo *copyinfo;
- Elf32_Addr bindaddr = 0xffffffff;
- extern void copyit ();
-
- unsigned char *kernel_image, *chip_buf;
- char *kernel_name = "unix";
- int fd;
- struct stat stb;
-
-
- switch (argc)
- {
- case 3:
- if (argv[2][0] == '$')
- sscanf (argv[2], "$%x", &bindaddr);
- else if (argv[2][0] == '0' &&
- (argv[2][1] == 'x' || argv[2][1] == 'X'))
- sscanf (argv[2]+2, "%x", &bindaddr);
- else
- sscanf (argv[2], "%d", &bindaddr);
- /* fall into */
-
- case 2:
- kernel_name = argv[1];
- /* fall into */
-
- case 1:
- break;
-
- default:
- fprintf (stderr, "%s [kernel_file [bind_address]]\n", argv[0]);
- return 20;
- }
-
- if (stat (kernel_name, &stb) == -1)
- {
- fprintf (stderr, "%s: can't access %s, %s.\n",
- argv[0], kernel_name, strerror (errno));
- return 20;
- }
-
- if (bindaddr <= 0x200000)
- {
- fprintf (stderr, "%s: can't bind into CHIP memory.\n", argv[0]);
- return 20;
- }
-
-
- ExpansionBase = (struct ExpansionBase *)
- OpenLibrary (reloc (EXPANSIONNAME), 0);
- if (ExpansionBase == NULL)
- {
- fprintf (stderr, "%s: can't open expansion.library.\n", argv[0]);
- return 20;
- }
-
- chip_buf = AllocMem (CHIP_BUF_SIZE, MEMF_CHIP);
- if (! chip_buf)
- {
- /* well.. if we can't get that much chip mem, displaying some
- * message probably won't work either, so quit quietly .. */
- CloseLibrary (ExpansionBase);
- return 20;
- }
-
- /*
- * Open the kernel file, and read it into a large enough buffer
- */
- kernel_image = AllocMem (stb.st_size, MEMF_FAST);
- if (! kernel_image)
- {
- CloseLibrary (ExpansionBase);
- FreeMem (chip_buf, CHIP_BUF_SIZE);
- fprintf (stderr, "%s: out of memory loading kernel.\n", argv[0]);
- return 20;
- }
-
- if ((fd = open (kernel_name, 0)) < 0)
- {
- fprintf (stderr, "%s: can't open %s for read access, %s\n",
- argv[0], kernel_name, strerror (errno));
- shutup:
- CloseLibrary (ExpansionBase);
- FreeMem (chip_buf, CHIP_BUF_SIZE);
- FreeMem (kernel_image, stb.st_size);
- return 20;
- }
-
- if (read (fd, kernel_image, stb.st_size) != stb.st_size)
- {
- fprintf (stderr, "%s: can't read %s, %s.\n",
- argv[0], kernel_name, strerror (errno));
- goto shutup;
- }
- close (fd);
-
- /*
- * Allocate space in chip memory to hold the bootinfo structure, and
- * then go through the various lists and initialize bootinfo.
- */
-
- nbytes = sizeof (*bi);
- bi = (struct bootinfo *) AllocMem (nbytes, MEMF_CLEAR | MEMF_CHIP);
-
- acp = bi -> autocon;
- for (cdp = (struct ConfigDev *) ExpansionBase -> BoardList.lh_Head ;
- cdp -> cd_Node.ln_Succ ;
- cdp = (struct ConfigDev *) cdp -> cd_Node.ln_Succ) {
- *acp++ = *cdp;
- }
-
- mhp = bi -> memory;
- for (mnp = (struct MemHeader *) (*ABSEXECBASE) -> MemList.lh_Head;
- mnp -> mh_Node.ln_Succ;
- mnp = (struct MemHeader *) mnp -> mh_Node.ln_Succ)
- {
- *mhp = *mnp;
- #ifdef SUPERKICKSTART_KLUDGE
- /* this trick gets us the 512K back that are used as kick-`WORM' */
- if (mhp->mh_Upper == (APTR)0x07f80000) mhp->mh_Upper = (APTR)0x08000000;
- #endif
- mhp++;
- }
-
- /*
- * Check to see if a specific binding address has been specified
- * in the info block. A value of 0xFFFFFFFF indicates that the
- * boot code is to do automatic binding (the default) by scanning
- * the system's memory list and picking an appropriate relocation
- * address.
- */
-
- if (bindaddr == 0xFFFFFFFF) bindaddr = bind ();
-
- /*
- * Do the relocation. Note that for now, the text and data segments
- * must be contiguous in the relocatable ELF file, with text first.
- * This condition is tested for and enforced by this version. At some
- * point, the information passed to the copyit() function needs to be
- * expanded to allow the text and data segments to occupy noncontiguous
- * memory prior to transfer to the final execution location by copyit().
- */
-
- bd = &(bi -> bootdata);
- rel (kernel_image, bindaddr, bd);
- if ((bd -> bd_toffset + bd -> bd_tsize != bd -> bd_doffset)
- || (bd -> bd_tvaddr + bd -> bd_tsize != bd -> bd_dvaddr)) {
- fprintf (stderr, "%s: Text and data not contiguous!\n",
- argv[0]);
- goto shutup;
- }
-
- /*
- * Initialize the copyinfo structure, copy the code for the copyit
- * function into chip memory, and then call the copy function in
- * supervisor mode.
- */
-
- copyinfo = (struct copyinfo *) chip_buf;
- copyinfo -> ci_loadbuf = kernel_image + bd -> bd_toffset;
- copyinfo -> ci_vaddr = bd -> bd_tvaddr;
- copyinfo -> ci_size = bd -> bd_tsize + bd -> bd_dsize;
- copyinfo -> ci_entry = bd -> bd_entry;
- copyinfo -> ci_d0 = EXEC1; /* boot method */
- copyinfo -> ci_d1 = (unsigned long) bi; /* bootinfo struct */
- memcpy (copyinfo -> ci_copyit, reloc (copyit), TD_SECTOR);
- return (supervisor (copyinfo -> ci_copyit, copyinfo));
- }
-